package middleware

import (
	"bytes"
	"github.com/gin-gonic/gin"
	"io"
	"log"
	"net/http"
	model2 "server/internal/app/model"
	"server/internal/database"
	"server/internal/pkg/response"
	"server/pkg/jwts"
	"strconv"
	"strings"
	"time"
)

// LoginVerification 登录验证
func LoginVerification(r *gin.Context) {
	getToken := r.Request.Header.Get("batoken")
	if getToken == "" {
		response.NotLogin(r, 101, "未登录")
		return
	}

	userInfo, err := jwts.Decrypt(getToken)
	if err != nil {
		response.NotLogin(r, 106, "登录超时")
		return
	}

	Db := database.DB
	var user model2.User
	Db.Model(&user).Where("id = ?", userInfo.ID).First(&user)

	if user.ID == 0 {
		response.NotLogin(r, 101, "无效的登录")
		return
	}

	user.Password = ""
	if user.Status == "0" {
		response.NotLogin(r, 101, "账号已被冻结")
		return
	}

	adminGroup := model2.UserGroup{}
	Db.Model(&adminGroup).Where("id = ?", user.GroupId).First(&adminGroup)

	r.Set("rules", adminGroup.Rules)
	//r.Set("rules", "*") //假的
	r.Set("group_id", user.GroupId)
	r.Set("tissue_id", user.TissueId)
	r.Set("userInfo", user)

}

// PermissionVerification 权限验证
func PermissionVerification(r *gin.Context) {
	rules, _ := r.Get("rules")
	rulesString := rules.(string)
	Db := database.DB

	path := r.Request.URL.Path
	path = strings.Trim(path, "/")
	//超级管理员不需要验证权限
	if rulesString != "*" {
		groupIds := strings.Split(rulesString, ",")

		var menuRule []model2.MenuRule
		Db.Model(&menuRule).Where("name = ?", path).Find(&menuRule)
		if len(menuRule) > 0 { //菜单表存在的接口需要验证权限， 不存在的不验证， 如需要验证权限 请把接口存到菜单表
			if !isAuthority(groupIds, menuRule) {
				response.NotAuthority(r)
				return
			}
		}
	}

	OperationLog(r, path) //系统操作日志

}

// 验证 是否有该接口权限
func isAuthority(ids []string, menuRule []model2.MenuRule) bool {

	for _, v := range ids {
		for _, vv := range menuRule {
			idStr := strconv.Itoa(vv.ID)
			if v == idStr {
				return true
			}
		}

	}
	return false
}

// OperationLog 系统操作日志
func OperationLog(r *gin.Context, path string) {

	userInfo, _ := r.Get("userInfo")
	user := userInfo.(model2.User)

	if path != "admin/index" {
		bodyBytes, err := io.ReadAll(r.Request.Body)
		if err != nil {
			log.Println("操作日志：", path, "写入失败：", err.Error())
			return
		}

		// 将读取的body数据重新写回到请求中
		r.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))

		data := string(bodyBytes)
		ip := r.ClientIP()
		Db := database.DB
		UserLog := model2.SystemLog{}
		t := time.Now()
		newTime := t.Add(time.Hour * -2)
		Db.Select("id,user_id,url,data,ip,create_time").
			Where("user_id = ? and url = ? and data = ? and ip = ? and create_time >= ?", user.ID, path, data, ip, newTime.Unix()).
			First(&UserLog)
		if UserLog.ID > 0 {
			return
		}

		table := model2.MenuRule{}
		var title string
		Db.Model(&table).Where("name = ?", path).First(&table)

		title = table.Title
		if table.Pid > 0 {
			table2 := model2.MenuRule{}
			Db.Model(&table2).Where("id = ?", table.Pid).First(&table2)
			title = table2.Title + "->" + title
		}
		if path == "user/login" {
			title = "登录"
		}
		if title == "" {
			return
		}
		UserLog.Title = title
		UserLog.UserId = user.ID
		UserLog.Username = user.Username
		UserLog.Url = path
		UserLog.Data = string(data)
		UserLog.Ip = ip
		UserLog.CreateTime = int(time.Now().Unix())
		Db.Create(&UserLog)
	}

}

// Cors 跨域
func Cors() gin.HandlerFunc {
	return func(context *gin.Context) {
		method := context.Request.Method
		context.Header("Access-Control-Allow-Origin", "*")
		context.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,batoken,type,responseType")
		context.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
		context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
		context.Header("Access-Control-Allow-Credentials", "true")
		if method == "OPTIONS" {
			context.AbortWithStatus(http.StatusNoContent)
		}
		context.Next()
	}
}
